#include <ev.h>
#include <amqpcpp.h>
#include <amqpcpp/libev.h>
#include <openssl/ssl.h>
#include <openssl/opensslv.h>

// 消息回调处理函数：接收到消息后，将消息内容输出并确认接收
void MessageCb(AMQP::TcpChannel *channel, const AMQP::Message &message, uint64_t deliveryTag, bool redelivered)
{
    std::string msg;
    msg.assign(message.body(), message.bodySize());
    std::cout << "Received Message: " << msg << std::endl;
    channel->ack(deliveryTag); // 确认消息已被处理
}

int main()
{
    // 1. 实例化 libev 事件循环：创建事件循环对象，用于管理 I/O 事件
    auto *loop = EV_DEFAULT;

    // 2. 实例化 AMQP LibEvHandler：将 AMQP 库与 libev 事件循环结合
    AMQP::LibEvHandler handler(loop);

    // 3. 实例化 AMQP 连接对象：设置连接参数，连接到 RabbitMQ 服务器
    AMQP::Address address("amqp://root:123456@127.0.0.1:5672/"); // RabbitMQ 连接地址（用户名、密码、IP 和端口）
    AMQP::TcpConnection connection(&handler, address); // 使用 LibEvHandler 处理网络事件

    // 4. 实例化 AMQP 信道对象：信道用于消息的发送和接收
    AMQP::TcpChannel channel(&connection); // 信道是与 RabbitMQ 服务器进行通信的通道

    // 5. 声明交换机：创建一个直接交换机（Direct Exchange），用于消息路由
    channel.declareExchange("test-exchange", AMQP::ExchangeType::direct)
        .onError([](const char *message) {
            std::cout << "声明交换机失败：" << message << std::endl;
            exit(0); // 如果声明交换机失败，退出程序
        })
        .onSuccess([]() {
            std::cout << "test-exchange 交换机创建成功！" << std::endl;
        });

    // 6. 声明队列：创建一个队列（Queue），用于接收消息
    channel.declareQueue("test-queue")
        .onError([](const char *message) {
            std::cout << "声明队列失败：" << message << std::endl;
            exit(0); // 如果声明队列失败，退出程序
        })
        .onSuccess([]() {
            std::cout << "test-queue 队列创建成功！" << std::endl;
        });

    // 7. 绑定交换机与队列：将交换机和队列绑定在一起，确保消息可以路由到队列
    channel.bindQueue("test-exchange", "test-queue", "test-queue-key")
        .onError([](const char *message) {
            std::cout << "交换机与队列绑定失败：" << message << std::endl;
            exit(0); // 如果绑定失败，退出程序
        })
        .onSuccess([]() {
            std::cout << "交换机与队列绑定成功！" << std::endl;
        });

    // 8. 订阅队列消息：设置回调函数来处理从队列接收到的消息
    // 使用 std::bind 来绑定回调函数和相关参数
    auto callback = std::bind(MessageCb, &channel, std::placeholders::_1, std::placeholders::_2, std::placeholders::_3);
    channel.consume("test-queue", "consume-tag")  // 创建消费（订阅）操作，指定队列和消费者标签
        .onReceived(callback) // 设置接收到消息时的回调函数
        .onError([](const char *message) {
            std::cout << "订阅队列消息失败：" << message << std::endl;
            exit(0); // 如果订阅失败，退出程序
        });

    // 9. 启动事件循环：开始 libev 事件循环，等待和处理所有的网络 I/O 事件
    ev_run(loop, 0);

    return 0; // 程序结束
}
